package com.geovis.emergency.spd.biz.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import com.geovis.common.auth.context.AuthUser;
import com.geovis.common.auth.props.AuthProperties;
import com.geovis.common.auth.service.IAuthService;
import com.geovis.common.core.constant.CommonConstants;
import com.geovis.common.core.exception.BizException;
import com.geovis.emergency.spd.biz.system.mapper.SystemUserMapper;
import com.geovis.emergency.spd.biz.system.service.ISystemResourcesService;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.geovis.emergency.spd.entity.system.pojo.constant.SystemConstant;
import com.geovis.emergency.spd.entity.system.pojo.dto.LoginUserDTO;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemResourcesDTO;
import com.geovis.emergency.spd.entity.system.pojo.dto.SystemResourcesQueryDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.PathContainer;
import org.springframework.stereotype.Service;
import org.springframework.web.util.pattern.PathPatternParser;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * 实现权限框架接口
 * </p>
 *
 * @author 王响
 * @since 2022-04-15
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SystemAuthServiceImpl implements IAuthService {

    private final AuthProperties authProperties;
    private final SystemUserMapper systemUserMapper;

    private final ISystemResourcesService systemResourcesService;

    private final RedisTemplate redisTemplate;

    private final String CACHE_KEY_RESOURCES_ROLE = "resources_role";


    @Override
    public AuthUser getByUserName(String username) {
        LoginUserDTO LoginUserDTO = systemUserMapper.selectByUsername(username);
        if (ObjectUtil.isEmpty(LoginUserDTO)) {
            throw new BizException("用户不存在");
        }
        if ("0".equals(LoginUserDTO.getDataStatus())) {
            throw new BizException("用户已停用");
        }
        return BeanUtil.copyProperties(LoginUserDTO, AuthUser.class);
    }

    @Override
    public List<String> getResourceRole(String resourceApiUrl) {
        if (ObjectUtil.isEmpty(resourceApiUrl)) {
            return CollUtil.list(false);
        }
        String key = getKey(resourceApiUrl);
        SystemResourcesDTO systemResourcesDTO = (SystemResourcesDTO) redisTemplate.opsForHash().get(CACHE_KEY_RESOURCES_ROLE, key);
        // 如果库里面没有维护api接口，那么授予普通角色可以访问
        if (ObjectUtil.isEmpty(systemResourcesDTO)) {
            return CollUtil.list(false, authProperties.getDefaultRole());
        }
        return CollUtil.list(false, systemResourcesDTO.getRoleList());
    }

    /**
     * 跟请求url 获取对应的系统接口地址
     *
     * @param resourceApiUrl 请求url
     * @return
     */
    private String getKey(String resourceApiUrl) {

        Set<String> keys = redisTemplate.opsForHash().keys(CACHE_KEY_RESOURCES_ROLE);
        for (String key : keys) {
            if (PathPatternParser.defaultInstance.parse(key).matches(PathContainer.parsePath(resourceApiUrl))) {
                return key;
            }
        }
        return resourceApiUrl;
    }


    /**
     * 缓存角色资源信息
     */
    @PostConstruct
    public void cacheSystemResourcesRole() {
        log.info(">>>>>>>>>>> 缓存接口资源角色信息 start <<<<<<<<<<<<<");
//        redisTemplate.delete(CACHE_KEY_RESOURCES_ROLE);
//        SystemResourcesQueryDTO queryDTO = new SystemResourcesQueryDTO();
//        queryDTO.setType(CollUtil.list(false, SystemConstant.SYSTEM_RESOURCE_API));
//        List<SystemResourcesDTO> list = systemResourcesService.listWithRole(queryDTO);
//        if (ObjectUtil.isNotEmpty(list)) {
//            Map<String, SystemResourcesDTO> map = IterUtil.toMap(list, SystemResourcesDTO::getUrl);
//            redisTemplate.opsForHash().putAll(CACHE_KEY_RESOURCES_ROLE, map);
//        }
        log.info(">>>>>>>>>>> 缓存接口资源角色信息 end <<<<<<<<<<<<");
    }

}
